﻿using System;
using System.Collections.Generic;
using System.Linq;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Practices.Unity;
using Reactor.Client.ViewModel;
using Reactor.Client.Web.Data;
using Reactor.Client.Web.Services;
using Reactor.Messages.Commands.Core;

namespace Reactor.Client.Services
{
    public interface IReactorServiceAgent
    {
        /// <summary>
        /// Gets ViewModels representing all known Reactor Cores and passes them to the supplied callback.
        /// </summary>
        /// <param name="callback">The callback.</param>
        void GetAllReactorCores(Action<IEnumerable<CoreViewModel>> callback);

        void GetAllServicesByCore(string coreName, Action<IEnumerable<ServiceViewModel>> callback);

        void GetAllServicePackages(Action<IEnumerable<ServicePackageViewModel>> callback);

        void GetConfigurationValue(string key, Action<string> callback);
        
        void SendOrphanCommand(OrphanService orphanServiceCommand);

        void SendTransferCommand(TransferService transferServiceCommand);

        void SendUpgradeServiceCommand(UpgradeService upgradeServiceCommand);
    }

    public class ReactorServiceAgent : IReactorServiceAgent
    {
        private readonly CoreDomainContext _coreDomainContext;

        public ReactorServiceAgent()
        {
            _coreDomainContext = new CoreDomainContext();
        }

        /// <summary>
        /// Gets entity classes representing all known Reactor Cores and passes them to the supplied callback.
        /// </summary>
        /// <param name="callback">The callback.</param>
        public void GetAllReactorCores(Action<IEnumerable<CoreViewModel>> callback)
        {
            _coreDomainContext.Load(_coreDomainContext.GetCoresQuery(), lo =>
            {
                var cores = lo.Entities.Select(entity => App.Container.Resolve<CoreViewModel>(new ParameterOverride("core", entity))).ToList();

                callback.Invoke(cores);
            }, null);
        }

        public void GetAllServicesByCore(string coreName, Action<IEnumerable<ServiceViewModel>> callback)
        {
            _coreDomainContext.Load(_coreDomainContext.GetServicesByCoreQuery(coreName), lo =>
            {
                var services = lo.Entities.Select(entity => App.Container.Resolve<ServiceViewModel>(new ParameterOverride("service", entity))).ToList();

                callback.Invoke(services);
            }, null);
        }

        public void GetAllServicePackages(Action<IEnumerable<ServicePackageViewModel>> callback)
        {
            _coreDomainContext.Load(_coreDomainContext.GetAllServicePackageInfoQuery(), lo =>
            {
                var cores = lo.Entities.Select(entity => new ServicePackageViewModel(entity)).ToList();

                callback.Invoke(cores);
            }, null);
        }

        public void GetConfigurationValue(string key, Action<string> callback)
        {
            _coreDomainContext.Load(_coreDomainContext.GetConfigurationItemQuery(key), lo =>
            {
                var single = lo.Entities.FirstOrDefault();

                if (single != null)
                    callback.Invoke(single.ConfigValue);
                else
                    callback.Invoke(null);
            }, null);
        }

        public void SendOrphanCommand(OrphanService orphanServiceCommand)
        {
            
        }

        public void SendTransferCommand(TransferService transferServiceCommand)
        {
            
        }

        public void SendUpgradeServiceCommand(UpgradeService upgradeServiceCommand)
        {
            
        }
    }

    public class DesignerServiceAgent : IReactorServiceAgent
    {
        /// <summary>
        /// Gets ViewModels representing all known Reactor Cores and passes them to the supplied callback.
        /// </summary>
        /// <param name="callback">The callback.</param>
        public void GetAllReactorCores(Action<IEnumerable<CoreViewModel>> callback)
        {
            var dialogService = App.Container.Resolve<IDialogService>();
            var messenger = App.Container.Resolve<IMessenger>();
            callback.Invoke(new List<CoreViewModel>
                                {
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "nn-akilhoffer-01", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreA", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromHours(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreB", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreC", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreD", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreE", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreF", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreG", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreH", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreI", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreJ", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                    new CoreViewModel(messenger, this, dialogService, new ReactorCore{Name = "CoreK", Version = "1.0.0.0", ServiceCount = 5, LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))}),
                                });
        }

        public void GetAllServicesByCore(string coreName, Action<IEnumerable<ServiceViewModel>> callback)
        {
            var list = new List<Service>
                           {
                               new Service
                                {
                                    Name = "ServiceA",
                                    Version = "1.0.0.0",
                                    LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))
                                },
                                new Service
                                {
                                    Name = "ServiceB",
                                    Version = "1.2.0.0",
                                    LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))
                                },
                                new Service
                                {
                                    Name = "ServiceC",
                                    Version = "2.0.0.0",
                                    LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))
                                },
                                new Service
                                {
                                    Name = "ServiceD",
                                    Version = "1.0.3.0",
                                    LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))
                                },
                                new Service
                                {
                                    Name = "ServiceE",
                                    Version = "1.0.3.0",
                                    LastSeen = DateTime.Now.Subtract(TimeSpan.FromMinutes(1))
                                }
                           };

            if (coreName == "CoreB")
                list.Single(s => s.Name == "ServiceB").LastSeen = DateTime.Now.Subtract(TimeSpan.FromHours(1));

            callback.Invoke(list.Select(s => new ServiceViewModel(App.Container.Resolve<IMessenger>(), App.Container.Resolve<IDialogService>(), this, s)));
        }

        public void GetAllServicePackages(Action<IEnumerable<ServicePackageViewModel>> callback)
        {
            var list = new List<ServicePackageViewModel>
                           {
                                new ServicePackageViewModel(new ServicePackageInfo{Name = "ServiceA", Version = "1.0.0.0", ServicePackageId = Guid.NewGuid()}),
                                new ServicePackageViewModel(new ServicePackageInfo{Name = "ServiceB", Version = "1.2.0.0", ServicePackageId = Guid.NewGuid()}),
                                new ServicePackageViewModel(new ServicePackageInfo{Name = "ServiceB", Version = "1.3.0.0", ServicePackageId = Guid.NewGuid()}),
                                new ServicePackageViewModel(new ServicePackageInfo{Name = "ServiceB", Version = "1.3.5.0", ServicePackageId = Guid.NewGuid()}),
                                new ServicePackageViewModel(new ServicePackageInfo{Name = "ServiceC", Version = "1.0.0.0", ServicePackageId = Guid.NewGuid()}),
                                new ServicePackageViewModel(new ServicePackageInfo{Name = "ServiceD", Version = "1.0.0.0", ServicePackageId = Guid.NewGuid()}),
                           };
            callback.Invoke(list);
        }

        public void GetConfigurationValue(string key, Action<string> callback)
        {
            if (key == "HealthCheckInterval")
                callback.Invoke("00:03:00");
        }

        public void SendOrphanCommand(OrphanService orphanServiceCommand)
        {
            
        }

        public void SendTransferCommand(TransferService transferServiceCommand)
        {
            
        }

        public void SendUpgradeServiceCommand(UpgradeService upgradeServiceCommand)
        {
            
        }
    }
}
